/*
 * z80_registers.hpp
 *
 *  Created on: Jan 4, 2012
 *      Author: douglas
 */

struct reg8_t {

	union
	{
		u8 b;

		//Flag fields
		struct
		{
			u8 c       : 1;
			u8 n       : 1;
			u8 pv      : 1;
			u8 f3      : 1;
			u8 h       : 1;
			u8 f5      : 1;
			u8 z       : 1;
			u8 s       : 1;
		};

	};


	inline operator unsigned() const { return b; }
	inline unsigned operator   = (unsigned i) { return b   = i; }
	inline unsigned operator  |= (unsigned i) { return b  |= i; }
	inline unsigned operator  ^= (unsigned i) { return b  ^= i; }
	inline unsigned operator  &= (unsigned i) { return b  &= i; }
	inline unsigned operator <<= (unsigned i) { return b <<= i; }
	inline unsigned operator >>= (unsigned i) { return b >>= i; }
	inline unsigned operator  += (unsigned i) { return b  += i; }
	inline unsigned operator  -= (unsigned i) { return b  -= i; }
	inline unsigned operator  *= (unsigned i) { return b  *= i; }
	inline unsigned operator  /= (unsigned i) { return b  /= i; }
	inline unsigned operator  %= (unsigned i) { return b  %= i; }

	reg8_t() : b(0) {}
};

struct reg16_t {

	union {
		uint16 w;
		struct { uint8 h,l; };
	};

	inline operator unsigned() const { return w; }
	inline unsigned operator   = (unsigned i) { return w   = i; }
	inline unsigned operator  |= (unsigned i) { return w  |= i; }
	inline unsigned operator  ^= (unsigned i) { return w  ^= i; }
	inline unsigned operator  &= (unsigned i) { return w  &= i; }
	inline unsigned operator <<= (unsigned i) { return w <<= i; }
	inline unsigned operator >>= (unsigned i) { return w >>= i; }
	inline unsigned operator  += (unsigned i) { return w  += i; }
	inline unsigned operator  -= (unsigned i) { return w  -= i; }
	inline unsigned operator  *= (unsigned i) { return w  *= i; }
	inline unsigned operator  /= (unsigned i) { return w  /= i; }
	inline unsigned operator  %= (unsigned i) { return w  %= i; }

	reg16_t() : w(0) {}
};



struct regs_t
{
	//Address registers
	u16 pc, sp, IX, IY;
	u8 I;
	u8 R;

	union
	{
		struct
		{
			u8 C, B, E, D, L, H, F, A;
		};

		struct
		{
			u16 BC, DE, HL, AF;
		};

		struct
		{
			u8 temp1[6]; //unused. Only to match Flags with F register.

			struct //Used in the same place as F register.
			{
				u8 c       : 1;
				u8 n       : 1;
				u8 pv      : 1;
				u8 f3      : 1;
				u8 h       : 1;
				u8 f5      : 1;
				u8 z       : 1;
				u8 s       : 1;
			} Flags;

			u8 temp2;//unused. Only to match Flags with F register.
		};

	};

	u8 *r[10]; //this is a vector of pointer because of endianess. We cannot match directly in the union above.
	u8 rs[8]; //shadow registers.

	u16 * pair[6];

	u8 s;
	u16 ss;

	//Constructor
	regs_t()
	{
		//TODO: the initialization of r[] vector is for Intel endianess only. I need to add endianess check.
		r[0] = &B;
		r[1] = &C;
		r[2] = &D;
		r[3] = &E;
		r[4] = &H;
		r[5] = &L;
		r[6] = &F;
		r[7] = &A;
		r[8] = &I;
		r[9] = &R;

		pair[0] = (u16 *) &r[2];
		pair[1] = (u16 *) &r[4];
		pair[2] = (u16 *) &r[6];
		pair[3] = (u16 *) &sp;
		pair[4] = (u16 *) &IX;
		pair[5] = (u16 *) &IY;
	}
};
